package cn.genmer.test.security.rpc.v2.proxy;

import cn.genmer.test.security.rpc.v2.rpc.Dispatcher;
import cn.genmer.test.security.rpc.v2.rpc.protocol.GContent;
import cn.genmer.test.security.rpc.v2.rpc.transport.GClientFactory;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.concurrent.CompletableFuture;

public class GProxy {
    public static <T>T proxyGet(Class<T> classInfo){
        ClassLoader classLoader = classInfo.getClassLoader();
        Class<?>[] classes = {classInfo};

        //TODO Loacl Remote -> 确定最好都代理一下，方便增强
        Dispatcher dispatcher = Dispatcher.getDispatcher();
        return (T) Proxy.newProxyInstance(classLoader, classes, new InvocationHandler() {
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                // TODO 确定本地调用或者远程调用，用dispatcher区分
                Object res = null;
                Object o = dispatcher.get(classInfo.getName());
                if (o == null){
                    // RPC Header可变
                    String name = classInfo.getName();
                    String methodName = method.getName();
                    Class<?>[] parameterTypes = method.getParameterTypes();
                    GContent content = new GContent();
                    content.setArgs(args);
                    content.setName(name);
                    content.setMethodName(methodName);
                    content.setParameterTypes(parameterTypes);

                    /**
                     * 1. 缺失了注册发现（假设这里通过zk之类的第三方，作为consumer已经获得可以消费的provider）
                     * 2. 考虑第一层负载 - 面向provider
                     * 3. consumer 线程池 面向service不一样，方法不一样，并发就有木桶，有倾斜
                     *  ServerA
                     *   ipA:port（目前：一个连接）
                     *      socket1
                     *      socket2
                     *   ipB:port
                     *
                     */
//                    CompletableFuture<String> resF = GClientFactory.transport("RPC",content);
                    CompletableFuture<String> resF = GClientFactory.transport("HTTP",content);
                    res = resF.get(); // 阻塞的
                } else {
                    // local FC
                    try{
                        System.out.println("本地函数调用");
                        Class<?> clazz = o.getClass();
                        Method m = clazz.getMethod(method.getName(), method.getParameterTypes());
                        res = method.invoke(o, args);
                    }catch (Exception e){
                        e.printStackTrace();
                    }
                }
                return res;
            }
        });
    }
}
